const net = require('net');
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);

class PortManager {
  /**
   * 检查端口是否被占用
   * @param {number} port 要检查的端口号
   * @returns {Promise<boolean>} 如果端口被占用返回true，否则返回false
   */
  static async isPortInUse(port) {
    return new Promise((resolve) => {
      const server = net.createServer()
        .once('error', () => {
          resolve(true);
        })
        .once('listening', () => {
          server.close();
          resolve(false);
        })
        .listen(port);
    });
  }

  /**
   * 获取占用指定端口的进程PID
   * @param {number} port 端口号
   * @returns {Promise<number|null>} 进程PID，如果没有找到则返回null
   */
  static async getProcessOnPort(port) {
    try {
      // 使用lsof命令查找占用端口的进程
      const { stdout } = await execAsync(`lsof -i :${port} -t`);
      const pid = parseInt(stdout.trim());
      return isNaN(pid) ? null : pid;
    } catch (error) {
      return null;
    }
  }

  /**
   * 终止指定PID的进程
   * @param {number} pid 进程ID
   * @returns {Promise<boolean>} 是否成功终止进程
   */
  static async killProcess(pid) {
    try {
      await execAsync(`kill -9 ${pid}`);
      // 添加进程状态检查
      const isRunning = await this.isProcessRunning(pid);
      if (isRunning) {
        console.error(`终止进程${pid}失败`);
        return false;
      }
      return true;
    } catch (error) {
      console.error(`终止进程${pid}失败:`, error.message);
      return false;
    }
  }

  static async isProcessRunning(pid) {
    try {
      await execAsync(`ps -p ${pid}`);
      return true;
    } catch {
      return false;
    }
  }

  /**
   * 确保端口可用，如果被占用则尝试释放
   * @param {number} port 要确保可用的端口号
   * @returns {Promise<boolean>} 端口是否可用
   */
  static async ensurePortAvailable(port) {
    const isInUse = await this.isPortInUse(port);
    if (!isInUse) {
      return true;
    }

    const pid = await this.getProcessOnPort(port);
    if (!pid) {
      return false;
    }

    console.log(`端口 ${port} 被进程 ${pid} 占用，正在尝试释放...`);
    const killed = await this.killProcess(pid);
    if (killed) {
      console.log(`成功释放端口 ${port}`);
      return true;
    } else {
      console.error(`无法释放端口 ${port}`);
      return false;
    }
  }
}

module.exports = PortManager;